package com.gdust.gkyx.common.auth;

import com.gdust.gkyx.common.constant.RedisConst;
import com.gdust.gkyx.common.utils.JwtHelper;
import com.gdust.gkyx.vo.user.UserLoginVo;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * ClassName: UserLoginInterceptor
 * Package: com.gdust.gkyx.common.auth
 * Description:用户登录拦截器，主要负责从请求头中解析用户登录信息，并通过 Redis 校验登录状态。
 * 校验成功后，将用户信息存储到 ThreadLocal 中，供后续处理使用。
 *
 * @Author syun
 * @Create 2025/1/28 8:52
 * @Version 1.0
 */
public class UserLoginInterceptor implements HandlerInterceptor {
    // RedisTemplate 用于操作 Redis 数据
    private RedisTemplate redisTemplate;

    /**
     * 构造方法，注入 RedisTemplate 依赖
     *
     * @param redisTemplate Redis 操作工具类
     */
    public UserLoginInterceptor(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }


    /**
     * 拦截器的前置处理方法。
     * 在请求处理前，解析并校验用户登录信息，并将其存储到 ThreadLocal 中。
     *
     * @param request  当前请求对象
     * @param response 当前响应对象
     * @param handler  处理器对象（控制器方法等）
     * @return 返回 true 表示继续处理该请求
     * @throws Exception 可能抛出的异常
     */
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {
        // 从请求中获取并处理用户登录信息
        this.getUserLoginVo(request);
        return true;
    }

    /**
     * 从请求头中获取 token，解析用户信息，并将其存储到 ThreadLocal 中。
     *
     * @param request 当前请求对象
     */
    private void getUserLoginVo(HttpServletRequest request) {
        //从请求头获取token
        String token = request.getHeader("token");

        //判断token不为空
        if(!StringUtils.isEmpty(token)) {
            //从token获取userId
            Long userId = JwtHelper.getUserId(token);
            //根据userId到Redis获取用户信息
            UserLoginVo userLoginVo = (UserLoginVo)redisTemplate.opsForValue()
                    .get(RedisConst.USER_LOGIN_KEY_PREFIX + userId);
            //获取数据放到ThreadLocal里面
            if(userLoginVo != null) {
                // 将用户 ID 存入 ThreadLocal
                AuthContextHolder.setUserId(userLoginVo.getUserId());
                // 将仓库 ID 存入 ThreadLocal
                AuthContextHolder.setWareId(userLoginVo.getWareId());
                // 将完整的用户登录信息存入 ThreadLocal
                AuthContextHolder.setUserLoginVo(userLoginVo);
            }
        }
    }
}

